//
//  YLAppleAuthorization.swift
//  QingLiuSwift
//
//  Created by xyanl on 2024/8/23.
//  Copyright © 2024 考拉🐨. All rights reserved.
//

import UIKit
import AuthenticationServices

struct YLAppleAuthorizationModel: Decodable {
    /// 授权成功后返回的用户 id,苹果用户唯一标识符
    var userId: String = ""
    var identityToken: Data?
    var authorizationCode: Data?
    
    var identityTokenStr: String? {
        get {
            if identityToken == nil {
                return nil
            }
            return String(data: identityToken!, encoding: .utf8)
        }
    }
    
    var authorizationCodeStr: String? {
        get {
            if authorizationCode == nil {
                return nil
            }
            return String(data: authorizationCode!, encoding: .utf8)
        }
    }
    
    init(userId: String, identityToken: Data? = nil, authorizationCode: Data? = nil) {
        self.userId = userId
        self.identityToken = identityToken
        self.authorizationCode = authorizationCode
    }
}

enum YLAppleAuthorizationError: Error {
    case cancel
    case other
}


class YLAppleAuthorization: NSObject {
    
    static let share: YLAppleAuthorization = YLAppleAuthorization()
    
    var model: YLAppleAuthorizationModel?
    
    /// 用于接收和处理来自第三方的请求的闭包
    public typealias Handle = (Result<YLAppleAuthorizationModel, YLAppleAuthorizationError>) -> Void
    /// 用于接收和处理来自微信的请求的闭包
    var completionHandler: Handle!
    
    func checkAuth(_ completion: @escaping Handle) {
        completionHandler = completion
        
        // 基于用户的 Apple ID 授权用户，生成用户授权请求的一种机制
        let provider = ASAuthorizationAppleIDProvider()
        
        // 创建新的AppleID 授权请求
        let request: ASAuthorizationAppleIDRequest = provider.createRequest()
        
        // 在用户授权期间请求的联系信息
        request.requestedScopes = [.fullName, .email]
        
        // 由ASAuthorizationAppleIDProvider创建的授权请求 管理授权请求的控制器
        let authorizationController = ASAuthorizationController(authorizationRequests: [request])
        
        // 设置授权控制器通知授权请求的成功与失败的代理
        authorizationController.delegate = self
        // 设置提供 展示上下文的代理，在这个上下文中 系统可以展示授权界面给用户
        authorizationController.presentationContextProvider = self
        // 在控制器初始化期间启动授权流
        authorizationController.performRequests()
    }
}

extension YLAppleAuthorization: ASAuthorizationControllerDelegate {
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: any Error) {
        /**
         ASAuthorizationError
         .unknown  授权请求失败未知原因
         .canceled  用户取消了授权请求
         .notHandled  未能处理授权请求
         .failed  授权请求失败
         .invalidResponse  授权请求响应无效
         */
        if let err = error as? ASAuthorizationError {
            switch err.code {
            case .canceled:
                completionHandler(.failure(.cancel))
                
            default:
                completionHandler(.failure(.other))
            }
        }
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        
        switch authorization.credential {
        case let appleIDCredential as ASAuthorizationAppleIDCredential:
            // 苹果用户唯一标识符，该值在同一个开发者账号下的所有 App 下是一样的，开发者可以用该唯一标识符与自己后台系统的账号体系绑定起来。
            let userIdentifier = appleIDCredential.user
            let identityToken = appleIDCredential.identityToken
            let authorizationCode = appleIDCredential.authorizationCode
            
            // 用于判断当前登录的苹果账号是否是一个真实用户，取值有：unsupported、unknown、likelyReal
            // let realUserStatus = appleIDCredential.realUserStatus
            
            // 这里可以执行登录操作，比如将这些信息发送到您的服务器进行验证
            let model = YLAppleAuthorizationModel(userId: userIdentifier, identityToken: identityToken, authorizationCode: authorizationCode)
            self.model = model
            completionHandler(.success(model))
            
        default:
            break
        }
        
    }
}

extension YLAppleAuthorization: ASAuthorizationControllerPresentationContextProviding {
    // 确保您的 ViewController 遵循了 ASAuthorizationControllerPresentationContextProviding 协议
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        // 代理主要用于展示在哪里
        return xKeyWindow
    }
}
